package grpc.rpcserver;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: admin
 * @Description:
 * @Date: 2018/9/28 15:39
 */

public class RpcServer {
    // 端口
    private int port;
    // 线程池(处理客户端连接请求)
    private ThreadPoolExecutor executor = new ThreadPoolExecutor(6, 30, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(15));
    // map 存储服务提供的功能
    private Map<String, Class<?>> serviceRegistry = Collections.synchronizedMap(new HashMap<>());

    public RpcServer(int port) {
        this.port = port;
    }

    // 注册对外暴露的服务
    public void registryService(Class<?> inter, Class<?> impl) {
        serviceRegistry.put(inter.getName(), impl);
    }

    // 启动
    public void start() throws IOException {
        // socker 服务端
        ServerSocket serverSocket = new ServerSocket();
        // 绑定端口
        serverSocket.bind(new InetSocketAddress(port));
        System.out.println("rpcserver is starting listen port " + port);
        try {
            while (true) {
                // 接收客户端接连，放入线程池
                executor.execute(new RpcTask(serverSocket.accept()));
            }
        } finally {
            serverSocket.close();
        }
    }

    public void stop() {
        executor.shutdown();
    }

    private class RpcTask implements Runnable {

        private final Socket client;

        public RpcTask(Socket client) {
            this.client = client;
        }

        @Override
        public void run() {
            ObjectOutputStream outputStream = null;
            ObjectInputStream inputStream = null;
            try {
                // 客户端输入流
                inputStream = new ObjectInputStream(client.getInputStream());
                // 客户端输出流
                outputStream = new ObjectOutputStream(client.getOutputStream());
                // 读取客户端请求的接口名
                String interfaceName = inputStream.readUTF();
                // 读取客户端请求的接口方法名
                String methodName = inputStream.readUTF();
                // 读取客户端请求的接口方法的参数类型
                Class<?>[] parameterTypes = (Class<?>[]) inputStream.readObject();
                // 读取客户端请求的接口方法的参数
                Object[] parameters = (Object[]) inputStream.readObject();
                // 根据接口名获取实现类
                Class<?> serviceType = serviceRegistry.get(interfaceName);
                // 反射获取方法
                Method method = serviceType.getDeclaredMethod(methodName, parameterTypes);
                // 获取实现类的实例，执行方法
                Object result = method.invoke(serviceType.newInstance(), parameters);
                // 将返回值写入到输出流
                outputStream.writeObject(result);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (inputStream != null) inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (outputStream != null) {
                        outputStream.flush();
                        outputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (client != null) client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getId());
        }
    }
}

